#include "emfgrid.h"
#include "polygondata/polygondataiterators.h"
#include "color/colorscale.h"

EmfGrid::EmfGrid()
{
     _colorScaleDrawable = new EmfColorScaleDrawable();
}

void EmfGrid::setPolygonData(QSharedPointer<PolygonData> polygonData)
{
    _polygonData = polygonData;

}

void EmfGrid::draw(QGLWidget *textRenderer)
{
    double x, y;

    glBegin(GL_QUADS);
    for(int i = 0; i < MESH_SIZE-1 ; i++)
    {
        for(int j = 0; j < MESH_SIZE-1; j++)
        {
            x = _boundingBox.left() + i*_dx;
            y = _boundingBox.top() + j*_dy;

            glColor4f(_meshColors[i][j].redF(), _meshColors[i][j].greenF(), _meshColors[i][j].blueF(), _meshColors[i][j].alphaF());
            glVertex2d(x, y);

            glColor4f(_meshColors[i+1][j].redF(), _meshColors[i+1][j].greenF(), _meshColors[i+1][j].blueF(), _meshColors[i][j].alphaF());
            glVertex2d(x+_dx, y);

            glColor4f(_meshColors[i+1][j+1].redF(), _meshColors[i+1][j+1].greenF(), _meshColors[i+1][j+1].blueF(), _meshColors[i][j].alphaF());
            glVertex2d(x+_dx, y+_dy);

            glColor4f(_meshColors[i][j+1].redF(), _meshColors[i][j+1].greenF(), _meshColors[i][j+1].blueF(), _meshColors[i][j].alphaF());
            glVertex2d(x, y+_dy);
        }
    }
    glEnd();

    if(ColorScale::instance()->getMaxValue() != 1)
    {
        _colorScaleDrawable->setBoundingBox(_boundingBox);
        _colorScaleDrawable->draw(textRenderer);
    }
}

void EmfGrid::_getBoundingBox()
{
   QSharedPointer<ElementIterator> picketIterator = _polygonData->createPicketIterator();
   double left = 1e45;
   double right = -1e45;
   double top = -1e45;
   double bottom = 1e45;
   for(picketIterator->begin(); !picketIterator->isFinished(); picketIterator->next())
   {
       int id = picketIterator->currentKey();
       QVector<QSqlRecord> picketRec = _polygonData->getSqlRecord(id);
       double x = picketRec[0].value("x").toDouble();
       double y = picketRec[0].value("y").toDouble();

       if(x < left)
       {
           left = x;
       }
       if(x > right)
       {
           right = x;
       }
       if(y > top)
       {
           top = y;
       }
       if(y < bottom)
       {
           bottom = y;
       }
   }

   double width = right-left;
   double height = top-bottom;
   _boundingBox = QRectF(left-width*0.1, bottom-height*0.1, width*1.2, height*1.2);
}

double EmfGrid::_pow2(double number)
{
    return number*number;
}

double EmfGrid::_getDistance(QPointF p1, QPointF p2)
{
    return pow(_pow2(p1.x() - p2.x()) + _pow2(p1.y() - p2.y()), 0.5);
}

bool EmfGrid::_isPointsTooFar(QPointF p1, QPointF p2)
{
    return sqrt(_pow2(p1.x() - p2.x()) + _pow2(p1.y() - p2.y())) > 1000;
}

double EmfGrid::_getValueByPoint(QPointF point)
{
    QSharedPointer<ElementIterator> picketIterator = _polygonData->createPicketIterator();
    double totalDistance = 0;
    double emfValue = 0;
    for(picketIterator->begin(); !picketIterator->isFinished(); picketIterator->next())
    {
        int id = picketIterator->currentKey();
        QVector<QSqlRecord> picketRec = _polygonData->getSqlRecord(id);
        double x = picketRec[0].value("x").toDouble();
        double y = picketRec[0].value("y").toDouble();

        if(!_isPointsTooFar(point, QPointF(x, y)))
        {
            double valueEmf = _polygonData->getValueEmf(id);
            double invDist =  1/_getDistance(point, QPointF(x, y));
            totalDistance += invDist;
            emfValue += invDist*valueEmf;
        }
    }

    if(totalDistance == 0)
        return 0;
    return emfValue/totalDistance;
}

void EmfGrid::recalculateColors(QProgressDialog *progressHandler)
{
    if(progressHandler)
    {
        progressHandler->setLabelText("Calculating...");
        progressHandler->setValue(0);
    }

    double minValue = 1e50;
    double maxValue = -1e50;

    QSharedPointer<ColorScale> colorScale = ColorScale::instance();

    _getBoundingBox();
    _dx = _boundingBox.width() / MESH_SIZE;
    _dy = _boundingBox.height() / MESH_SIZE;
    double x, y, valueEmf;
    QColor color;
    for(int i = 0; i < MESH_SIZE; i++)
    {
        for(int j = 0; j < MESH_SIZE; j++)
        {
            x = _boundingBox.left() + i*_dx;
            y = _boundingBox.top() + j*_dy;


            _meshValues[i][j] = _getValueByPoint(QPointF(x, y));
            if(_meshValues[i][j] != 0)
            {
                if(minValue > _meshValues[i][j])
                    minValue = _meshValues[i][j];
                else if(maxValue < _meshValues[i][j])
                    maxValue = _meshValues[i][j];
            }
            qApp->processEvents();
            if(progressHandler)
            {
                progressHandler->setValue((100*i*MESH_SIZE + j)/(MESH_SIZE*MESH_SIZE));
            }
        }
    }

    colorScale->setBoundValues(262.6, 389.4);
   // colorScale->setBoundValues(minValue, maxValue);

    for(int i = 0; i < MESH_SIZE; i++)
    {
        for(int j = 0; j < MESH_SIZE; j++)
        {
            valueEmf = _meshValues[i][j];
            if(valueEmf != 0)
            {
                color = colorScale->getColor(valueEmf);
                _meshColors[i][j] = color;
            }
            else
            {
                _meshColors[i][j] = QColor(255, 255, 255, 0);
            }
        }
    }

     _colorScaleDrawable->setColorScale(colorScale.data());

    if(progressHandler)
    {
        progressHandler->setValue(100);
    }
}
